package com.dingreading.cloud.admin.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dingreading.cloud.admin.entity.StoreProductLogs;
import com.dingreading.cloud.admin.entity.StoreProducts;
import com.dingreading.cloud.admin.entity.StoreProjects;
import com.dingreading.cloud.admin.service.CmservicesService;
import com.dingreading.cloud.admin.service.StoreProductLogsService;
import com.dingreading.cloud.admin.service.StoreProductsService;
import com.dingreading.cloud.admin.service.StoreProjectsService;
import com.dingreading.cloud.admin.util.bean.CmorderUtil;
import com.dingreading.cloud.common.base.R;
import com.dingreading.cloud.common.util.*;
import com.mybatisflex.core.paginate.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@RestController
@RequestMapping(value = "/system/storeProducts/v2")
@Api(tags = "总部-门店产品管理")
public class StoreProductsControllerV2 {

    @Resource
    protected StoreProductsService storeProductsService;
    @Resource
    protected StoreProjectsService storeProjectsService;
    @Resource
    protected StoreProductLogsService storeProductLogsService;
    @Resource
    protected CmservicesService cmservicesService;


    @ApiOperation(value = "分页列表")
    @PostMapping(value = "/pageList", produces = "application/json; charset=UTF-8")
    public R<Object> pageList(
            @ApiParam(value = "分页公共类") PageUtil pageUtil,
            @ApiParam(value = "员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "产品名称") @RequestParam(value = "keyword", required = false) String keyword,
            @ApiParam(value = "数据来源 1.总部 2.门店") @RequestParam(value = "source") Integer source,
            @ApiParam(value = "启用状态") @RequestParam(value = "enabled", required = false) Integer enabled
    ) {
        Page<StoreProducts> pageList = storeProductsService.pageList(pageUtil, keyword, source, enabled);

        List<StoreProducts> list = pageList.getRecords();
        if (CollectionUtils.isNotEmpty(list)) {
            List<String> productUids = list.stream().map(StoreProducts::getUid).collect(Collectors.toList());
            List<StoreProductLogs> logs = storeProductLogsService.listByProductUids(productUids);
            Map<String, List<StoreProductLogs>> map = null;
            if (CollectionUtils.isNotEmpty(logs)) {
                map = logs.stream().collect(Collectors.groupingBy(StoreProductLogs::getProductUid));
            }
            if (null != map) {
                for (StoreProducts products : list) {
                    products.setList(map.get(products.getUid()));
                }
            }
        }

        PageBeanDto data = new PageBeanDto();
        data.setTotal(pageList.getTotalRow());
        data.setList(list);
        return R.ok(data);
    }


    @ApiOperation(value = "获取信息")
    @PostMapping(value = "/getBean", produces = "application/json; charset=UTF-8")
    public R<Object> getBean(
            @ApiParam(value = "员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "产品uid") @RequestParam(value = "uid") String uid
    ) {
        StoreProducts data = storeProductsService.getByUid(uid);

        if (null != data) {
            List<StoreProductLogs> logs = storeProductLogsService.listByStoreUidAndProductUid(uid);
            data.setList(logs);
        }
        return R.ok(data);
    }

    @Transactional(rollbackFor = DescribeException.class)
    @ApiOperation(value = "创建/编辑信息")
    @PostMapping(value = "/newBean", produces = "application/json; charset=UTF-8")
    public R<Object> newBean(
            @ApiParam(value = "员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "产品uid") @RequestParam(value = "uid", required = false) String uid,
            @ApiParam(value = "产品名称") @RequestParam(value = "productName") String productName,
            @ApiParam(value = "产品类型 1.引流产品") @RequestParam(value = "productType", required = false) Integer productType,
            @ApiParam(value = "备注") @RequestParam(value = "remark", required = false) String remark,
            @ApiParam(value = "服务集合 {name:'',projectUid:'',days:0,lessons:0}") @RequestParam(value = "projectJson") String projectJson,
            @ApiParam(value = "门店合作类型") @RequestParam(value = "cooperationType") String cooperationType,
            @ApiParam(value = "运营类型") @RequestParam(value = "operationType") String operationType
    ) throws Exception {
        if (StringUtils.isBlank(projectJson))
            return R.fail("请先添加服务");

        JSONArray array = JSONArray.parseArray(projectJson);
        if (CollectionUtils.isEmpty(array))
            return R.fail("请先添加服务");
        if (array.size() > 10)
            return R.fail("产品下不能添加超过10条产品记录");

        Set<String> projectUids = new HashSet<>();
        for (int k = 0; k < array.size(); k++) {
            JSONObject jsonObject = array.getJSONObject(k);
            String name = jsonObject.getString("name");
            String projectUid = jsonObject.getString("projectUid");
            Integer days = jsonObject.getInteger("days");
            if (StringUtils.isBlank(projectUid))
                return R.fail("请选择服务");
            if (StringUtils.isBlank(name))
                return R.fail("请填写服务名称");
            if (null == days || days <= 0)
                return R.fail("请填写正确的活动天数");
            projectUids.add(projectUid);
        }

        boolean b = storeProductsService.haveName(uid, productName);
        if (b) return R.fail("名称重复了");

        List<StoreProjects> storeProjects = storeProjectsService.listByUids(new ArrayList<>(projectUids));
        if (CollectionUtils.isEmpty(storeProjects)) return R.fail("项目获取失败");
        if (projectUids.size() != storeProjects.size()) return R.fail("项目获取丢失");
        Map<String, StoreProjects> projectsMap = storeProjects.stream().collect(Collectors.toMap(StoreProjects::getUid, Function.identity()));

        List<StoreProductLogs> logs = new ArrayList<>();
        for (int j = 0; j < array.size(); j++) {
            JSONObject jsonObject = array.getJSONObject(j);
            String name = jsonObject.getString("name");
            String projectUid = jsonObject.getString("projectUid");
            Integer days = jsonObject.getInteger("days");
            Integer lessons = jsonObject.getInteger("lessons");

            StoreProjects projects = projectsMap.get(projectUid);
            if (CmorderUtil.isConsumeLesson(projects.getLessonStatus(), projects.getFreeStatus())) {
                if (null == lessons || lessons <= 0)
                    return R.fail("请填写正确的活动次数");
            }

            StoreProductLogs log = new StoreProductLogs();
            log.setProjectUid(projectUid);
            log.setName(name);
            log.setDays(days);
            log.setLessons(lessons);

            logs.add(log);
        }

        String dateTime = DateUtil.getNowDateminStr();
        StoreProducts data = null;
        boolean isNew = false;
        if (StringUtils.isBlank(uid)) {
            // 创建
            isNew = true;
            // 获取最大的主渠道展示序号
            int maxOrderNum = storeProductsService.getMaxOrderNum() + 1;

            uid = "PKG" + dateTime;
            data = new StoreProducts();
            data.setStoreUid(null);
            data.setUid(uid);
            data.setOrderNum(maxOrderNum);
            data.setEnabled(1);
            data.setSource(1);
            data.setAddStaffUid(headStaffUid);
            data.setAddStaffName(headStaffUid);
        } else {
            // 编辑
            data = storeProductsService.getByUid(uid);
            if (null == data) return R.fail("获取失败");
            if (!data.getSource().equals(1)) return R.fail("非总部信息不能操作");
            //TODO 判断是否添加到会员订单，已加入则不能再编辑
            if (!data.getProductName().equals(productName)) {
                String msg = useProduct(uid);
                if (StringUtils.isNotBlank(msg))
                    return R.fail(msg);
            }
        }
        data.setProductName(productName);
        data.setProductType(productType);
        data.setProjectNum(logs.size());
        data.setCooperationType(cooperationType);
        data.setOperationType(operationType);
        data.setRemark(NepUtil.nullToZero(remark));
        data.setLastStaffUid(headStaffUid);
        data.setLastStaffName(headStaffName);

        // 创建产品服务相关
        for (int j = 0; j < logs.size(); j++) {
            StoreProductLogs log = logs.get(j);
            StoreProjects storeProject = projectsMap.get(log.getProjectUid());
            if (null == storeProject)
                throw new DescribeException(500, "服务获取失败");

            String logUid = "PK" + dateTime + (j + 1);
            log.setStoreUid(null);
            log.setUid(logUid);
            log.setProductUid(uid);
            log.setProductName(productName);
            log.setProjectName(storeProject.getProjectName());
            log.setLessonStatus(storeProject.getLessonStatus());
            log.setFreeStatus(storeProject.getFreeStatus());
            log.setProductType(productType);
            log.setRemark("");
            log.setEnabled(1);
            log.setSource(1);
            log.setAddStaffUid(headStaffUid);
            log.setAddStaffName(headStaffName);
            log.setLastStaffUid(headStaffUid);
            log.setLastStaffName(headStaffName);
        }

        // 创建产品
        storeProductsService.saveOrUpdate(data);
        // 按产品uid删除原相关记录
        if (!isNew) {
            long l = storeProductLogsService.dropByProductUid(uid);
            if (l <= 0) throw new DescribeException("删除产品相关服务失败");
        }
        // 创建产品相关记录
        storeProductLogsService.saveOrUpdateBatch(logs);

        return R.ok();
    }


    @ApiOperation(value = "删除信息")
    @PostMapping(value = "/dropBean", produces = "application/json; charset=UTF-8")
    public R<Object> dropBean(
            @ApiParam(value = "员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "产品uid") @RequestParam(value = "uid") String uid
    ) {
        StoreProducts data = storeProductsService.getByUid(uid);
        if (data == null) return R.fail("获取失败");
        if (!data.getSource().equals(1)) return R.fail("非总部信息不能操作");

        //TODO 判断是否添加到会员订单，已加入则不能再编辑
        String msg = useProduct(uid);
        if (StringUtils.isNotBlank(msg))
            return R.fail(msg);

        long l = storeProductsService.dropBean(uid);
        if (l <= 0) return R.fail("删除失败");
        storeProductLogsService.dropByProductUid(uid);
        return R.ok();
    }


    @ApiOperation(value = "更新启用状态")
    @PostMapping(value = "/updateEnabled", produces = "application/json; charset=UTF-8")
    public R<Object> updateEnabled(
            @ApiParam(value = "员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "产品uid") @RequestParam(value = "uid") String uid,
            @ApiParam(value = "是否禁用 1.启用 0.禁用") @RequestParam(value = "enabled") Integer enabled
    ) {
        StoreProducts data = storeProductsService.getByUid(uid);
        if (data == null) return R.fail("获取失败");
        if (!data.getSource().equals(1)) return R.fail("非总部信息不能操作");

        boolean l = storeProductsService.updateEnabled(uid, enabled, headStaffUid, headStaffName);
        if (!l) return R.fail("更新状态失败");
        storeProductLogsService.updateEnabledByProductUid(uid, enabled, headStaffUid, headStaffName);
        return R.ok();
    }


    @ApiOperation(value = "上移/下移")
    @PostMapping(value = "/upOrDown", produces = "application/json; charset=UTF-8")
    public R<Object> upOrDown(
            @ApiParam(value = "员工uid") @RequestParam(value = "headStaffUid") String headStaffUid,
            @ApiParam(value = "员工名") @RequestParam(value = "headStaffName") String headStaffName,
            @ApiParam(value = "产品uid") @RequestParam(value = "uid") String uid,
            @ApiParam(value = "类型 1.上移 2.下移") @RequestParam(value = "type") Integer type
    ) {
        StoreProducts data = storeProductsService.getByUid(uid);
        if (data == null) return R.fail("获取失败");
        if (!data.getSource().equals(1)) return R.fail("非总部信息不能操作");

        if (type.equals(1)) {
            // 上移
            StoreProducts preData = storeProductsService.getLtShowOrder(data.getOrderNum());
            if (preData == null) return R.fail("已在最前");
            // 和前一条记录的序号互换
            Integer prevOrderNum = preData.getOrderNum();
            Integer curOrderNum = data.getOrderNum();
            // 序号互换
            storeProductsService.updateOrderNum(preData.getUid(), curOrderNum, headStaffUid, headStaffName);
            storeProductsService.updateOrderNum(uid, prevOrderNum, headStaffUid, headStaffName);
        } else if (type.equals(2)) {
            // 下移
            StoreProducts backData = storeProductsService.getGtShowOrder(data.getOrderNum());
            if (backData == null) return R.fail("已在最后");
            // 和后一条记录的序号互换
            Integer backOrderNum = backData.getOrderNum();
            Integer curOrderNum = data.getOrderNum();
            // 序号互换
            storeProductsService.updateOrderNum(backData.getUid(), curOrderNum, headStaffUid, headStaffName);
            storeProductsService.updateOrderNum(uid, backOrderNum, headStaffUid, headStaffName);
        } else {
            return R.fail("类型错误");
        }
        return R.ok();
    }

    /**
     * 判断是否添加到会员订单，已加入则不能再编辑
     */
    private String useProduct(String productUid) {
        boolean b = cmservicesService.haveProductUid(productUid);
        if (b)
            return "会员订单服务已使用，不能操作";
        return "";
    }

}
